;/////////////////////////////////////////////////////////////;
;                                                             ;
;                 SimpleDX11 Model Procedures                 ;
;                                                             ;
;                                                             ;
;                   (c) 2013 SimpleDX Team                    ;
;                                                             ;
;                         License: MIT                        ;
;                                                             ;
;/////////////////////////////////////////////////////////////;



;-//    Private structures    //
Structure Model_Template
  *vTable
  *p.Model
  *SD3D.Screen3D
  *Primitive.Primitive
  *Mesh.Mesh
  *Texture.Texture
  
  *VertexArray
  *IntexArray  
  
  Stride.l
  Topology.l 
  VertexCount.l   

EndStructure


;-//    Constructor    //
Procedure New_Model(*SD3D, Flags.l = #Null)
  Protected *this.Model_Template
 
  *this = AllocateMemory(SizeOf(Model_Template))
  InitializeStructure(*this, Model_Template)
  
  If *this
    *this\vTable            = ?Model_Class    
    *this\p                 = *this
    *this\SD3D               = *SD3D    

    *this\Primitive         = New_Primitive(Flags)
    *this\Mesh              = New_Mesh(*this\SD3D, Flags) 
    
    If Not *this\Primitive Or Not *this\Mesh  
      ProcedureReturn #False 
    EndIf      

      
    ProcedureReturn *this
  EndIf  
  ProcedureReturn #False  
EndProcedure




; Get the models primitive object 
Procedure Model_GetPrimitive(*this.Model_Template)
  ProcedureReturn *this\Primitive 
EndProcedure

; Get the models mesh object 
Procedure Model_GetMesh(*this.Model_Template)
  ProcedureReturn *this\Mesh 
EndProcedure

Procedure Model_LoadTexture(*this.Model_Template, File.s)
  *this\Texture = New_Texture(*this\SD3D)
  If *this\Texture\CreateTextureFromFile(File)    
    ProcedureReturn #False  
  EndIf  
  
  ProcedureReturn *this\Texture\GetTexture()
EndProcedure

; Add a triangle to the model
Procedure Model_AddTriangle(*this.Model_Template, TriangleSize.f, ColorValue = #Null)
  Protected *Color.D3DXCOLOR = AllocateMemory(SizeOf(D3DXCOLOR))
  
  GetColorFloats() 

  *this\Primitive\AddVertex(-TriangleSize, -TriangleSize, 0.0)  
  *this\Primitive\SetColor(*Color)
  *this\Primitive\SetUV(0.0, 1.0)
  *this\Primitive\SetNormal(0.0, 0.0, -1.0)   
  
  *this\Primitive\AddVertex(0.0, TriangleSize, 0.0)
  *this\Primitive\SetColor(*Color)
  *this\Primitive\SetUV(0.5, 0.0)
  *this\Primitive\SetNormal(0.0, 0.0, -1.0) 
  
  *this\Primitive\AddVertex(TriangleSize, -TriangleSize, 0.0)
  *this\Primitive\SetColor(*Color)
  *this\Primitive\SetUV(1.0, 1.0)
  *this\Primitive\SetNormal(0.0, 0.0, -1.0) 
  
  FreeMemory(*Color)
  
  *this\VertexCount = 3
  
  Dim Indices.l(2)
  Indices(0) = 0
  Indices(1) = 1
  Indices(2) = 2    
  
  *this\Primitive\AddIndicesArray(Indices(), 2)    

  FreeArray(Indices())
EndProcedure

; Add a Rectangle to the model
Procedure Model_AddRectangle(*this.Model_Template, RectangleSize.f, ColorValue = #Null)
  Protected *Color.D3DXCOLOR = AllocateMemory(SizeOf(D3DXCOLOR))
  
  GetColorFloats()
  
  *this\Primitive\AddVertex(-RectangleSize, RectangleSize, 0.0)  
  *this\Primitive\SetColor(*Color)  
  *this\Primitive\SetUV(0.0, 0.0)
  *this\Primitive\SetNormal(0.0, 0.0, -1.0) 
  
  *this\Primitive\AddVertex(RectangleSize, -RectangleSize, 0.0)
  *this\Primitive\SetColor(*Color)
  *this\Primitive\SetUV(1.0, 1.0)
  *this\Primitive\SetNormal(0.0, 0.0, -1.0) 
  
  *this\Primitive\AddVertex(-RectangleSize, -RectangleSize, 0.0)
  *this\Primitive\SetColor(*Color)
  *this\Primitive\SetUV(0.0, 1.0)
  *this\Primitive\SetNormal(0.0, 0.0, -1.0) 
  
  *this\Primitive\AddVertex(-RectangleSize, RectangleSize, 0.0)
  *this\Primitive\SetColor(*Color)
  *this\Primitive\SetUV(0.0, 0.0)
  *this\Primitive\SetNormal(0.0, 0.0, -1.0) 
  
  *this\Primitive\AddVertex(RectangleSize, RectangleSize, 0.0)
  *this\Primitive\SetColor(*Color)
  *this\Primitive\SetUV(1.0, 0.0)
  *this\Primitive\SetNormal(0.0, 0.0, -1.0)    
  
  *this\Primitive\AddVertex(RectangleSize, -RectangleSize, 0.0)
  *this\Primitive\SetColor(*Color)
  *this\Primitive\SetUV(1.0, 1.0)
  *this\Primitive\SetNormal(0.0, 0.0, -1.0)   
  
  FreeMemory(*Color)
  
  *this\VertexCount = 6
  
  Dim Indices.l(5)
  Indices(0) = 0
  Indices(1) = 1
  Indices(2) = 2    
  Indices(3) = 3
  Indices(4) = 4
  Indices(5) = 5   
  
  *this\Primitive\AddIndicesArray(Indices(), 5)    

  FreeArray(Indices())
EndProcedure


; Add a Cube to the model
Procedure Model_AddCube(*this.Model_Template, CubeSize.f,  ColorValue = #Null)
  Protected *Color.D3DXCOLOR = AllocateMemory(SizeOf(D3DXCOLOR)) 
  
  GetColorFloats() 


	;Front Face
	;///////////////////////////////////////////////	
	*this\Primitive\AddVertex(-CubeSize, -CubeSize, -CubeSize )  
  *this\Primitive\SetColor(*Color)
  *this\Primitive\SetUV(0.0, 1.0)
  *this\Primitive\SetNormal(0.0, 0.0, -1.0) 	
	
  *this\Primitive\AddVertex(-CubeSize, CubeSize, -CubeSize)
  *this\Primitive\SetColor(*Color)
  *this\Primitive\SetUV(0.0, 0.0)
  *this\Primitive\SetNormal(0.0, 0.0, -1.0)  

  *this\Primitive\AddVertex(CubeSize, CubeSize, -CubeSize)
  *this\Primitive\SetColor(*Color)
  *this\Primitive\SetUV(1.0, 0.0)
  *this\Primitive\SetNormal(0.0, 0.0, -1.0)    

  *this\Primitive\AddVertex(CubeSize, -CubeSize, -CubeSize)
  *this\Primitive\SetColor(*Color)
  *this\Primitive\SetUV(1.0, 1.0)
  *this\Primitive\SetNormal(0.0, 0.0, -1.0)    

  ;Back Face
  ;///////////////////////////////////////////////	
  *this\Primitive\AddVertex(-CubeSize, -CubeSize, CubeSize)  
  *this\Primitive\SetColor(*Color)
  *this\Primitive\SetUV(1.0, 1.0)
  *this\Primitive\SetNormal(0.0, 0.0, 1.0)

  *this\Primitive\AddVertex(CubeSize, -CubeSize, CubeSize)
  *this\Primitive\SetColor(*Color)
  *this\Primitive\SetUV(0.0, 1.0)
  *this\Primitive\SetNormal(0.0, 0.0, 1.0)

  *this\Primitive\AddVertex(CubeSize, CubeSize, CubeSize)
  *this\Primitive\SetColor(*Color)
  *this\Primitive\SetUV(0.0, 0.0)
  *this\Primitive\SetNormal(0.0, 0.0, 1.0)

  *this\Primitive\AddVertex(-CubeSize, CubeSize, CubeSize)
  *this\Primitive\SetColor(*Color)
  *this\Primitive\SetUV(1.0, 0.0)
  *this\Primitive\SetNormal(0.0, 0.0, 1.0)

  ;Top Face
  ;///////////////////////////////////////////////	
  *this\Primitive\AddVertex(-CubeSize, CubeSize, -CubeSize)  
  *this\Primitive\SetColor(*Color)
  *this\Primitive\SetUV(0.0, 1.0)
  *this\Primitive\SetNormal(0.0, 1.0, 0.0)

  *this\Primitive\AddVertex(-CubeSize, CubeSize, CubeSize)
  *this\Primitive\SetColor(*Color)
  *this\Primitive\SetUV(0.0, 0.0)
  *this\Primitive\SetNormal(0.0, 1.0, 0.0)

  *this\Primitive\AddVertex(CubeSize, CubeSize, CubeSize)
  *this\Primitive\SetColor(*Color)
  *this\Primitive\SetUV(1.0, 0.0)
  *this\Primitive\SetNormal(0.0, 1.0, 0.0)

  *this\Primitive\AddVertex(CubeSize, CubeSize, -CubeSize)
  *this\Primitive\SetColor(*Color)
  *this\Primitive\SetUV(1.0, 1.0)
  *this\Primitive\SetNormal(0.0, 1.0, 0.0)

  ;Bottom Face
  ;///////////////////////////////////////////////	
  *this\Primitive\AddVertex(-CubeSize, -CubeSize, -CubeSize) 
  *this\Primitive\SetColor(*Color)
  *this\Primitive\SetUV(1.0, 1.0)
  *this\Primitive\SetNormal(0.0, -1.0, 0.0)

  *this\Primitive\AddVertex(CubeSize, -CubeSize, -CubeSize)
  *this\Primitive\SetColor(*Color)
  *this\Primitive\SetUV(0.0, 1.0)
  *this\Primitive\SetNormal(0.0, -1.0, 0.0)

  *this\Primitive\AddVertex(CubeSize, -CubeSize, CubeSize)
  *this\Primitive\SetColor(*Color)
  *this\Primitive\SetUV(0.0, 0.0)
  *this\Primitive\SetNormal(0.0, -1.0, 0.0)

  *this\Primitive\AddVertex(-CubeSize, -CubeSize, CubeSize)
  *this\Primitive\SetColor(*Color)
  *this\Primitive\SetUV(1.0, 0.0)
  *this\Primitive\SetNormal(0.0, -1.0, 0.0)

  ;Left Face
  ;///////////////////////////////////////////////	
  *this\Primitive\AddVertex(-CubeSize, -CubeSize, CubeSize)  
  *this\Primitive\SetColor(*Color)
  *this\Primitive\SetUV(0.0, 1.0)
  *this\Primitive\SetNormal(-1.0, 0.0, 0.0) 
  
  *this\Primitive\AddVertex(-CubeSize, CubeSize, CubeSize)
  *this\Primitive\SetColor(*Color)
  *this\Primitive\SetUV(0.0, 0.0)
  *this\Primitive\SetNormal(-1.0, 0.0, -1.0)

  *this\Primitive\AddVertex(-CubeSize, CubeSize, -CubeSize)
  *this\Primitive\SetColor(*Color)
  *this\Primitive\SetUV(1.0, 0.0)
  *this\Primitive\SetNormal(-1.0, 0.0, 0.0)

  *this\Primitive\AddVertex(-CubeSize, -CubeSize, -CubeSize)
  *this\Primitive\SetColor(*Color)
  *this\Primitive\SetUV(1.0, 1.0)
  *this\Primitive\SetNormal(-1.0, 0.0, 0.0)
		
  ;Right Face
  ;///////////////////////////////////////////////	
  *this\Primitive\AddVertex(CubeSize, -CubeSize, -CubeSize)
  *this\Primitive\SetColor(*Color)
  *this\Primitive\SetUV(0.0, 1.0)
  *this\Primitive\SetNormal(1.0, 0.0, 0.0)  

  *this\Primitive\AddVertex(CubeSize, CubeSize, -CubeSize)
  *this\Primitive\SetColor(*Color)
  *this\Primitive\SetUV(0.0, 0.0)
  *this\Primitive\SetNormal(1.0, 0.0, 0.0) 

  *this\Primitive\AddVertex(CubeSize, CubeSize, CubeSize)
  *this\Primitive\SetColor(*Color)
  *this\Primitive\SetUV(1.0, 0.0)
  *this\Primitive\SetNormal(1.0, 0.0, 0.0)  

  *this\Primitive\AddVertex(CubeSize, -CubeSize, CubeSize)
  *this\Primitive\SetColor(*Color)
  *this\Primitive\SetUV(1.0, 1.0)
  *this\Primitive\SetNormal(1.0, 0.0, 0.0)  
 
  *this\VertexCount = 36
  
  Dim Indices.l(35)
  Indices(0) = 0
  Indices(1) = 1
  Indices(2) = 2    
  Indices(3) = 0
  Indices(4) = 2
  Indices(5) = 3
  
  Indices(6) = 4
  Indices(7) = 5
  Indices(8) = 6    
  Indices(9) = 4
  Indices(10) = 6
  Indices(11) = 7
  
  Indices(12) = 8
  Indices(13) = 9
  Indices(14) = 10    
  Indices(15) = 8
  Indices(16) = 10
  Indices(17) = 11 
  
  Indices(18) = 12
  Indices(19) = 13
  Indices(20) = 14    
  Indices(21) = 12
  Indices(22) = 14
  Indices(23) = 15  

  Indices(24) = 16
  Indices(25) = 17
  Indices(26) = 18    
  Indices(27) = 16
  Indices(28) = 18
  Indices(29) = 19 

  Indices(30) = 20
  Indices(31) = 21
  Indices(32) = 22    
  Indices(33) = 20
  Indices(34) = 22
  Indices(35) = 23   
  
  *this\Primitive\AddIndicesArray(Indices(), 35)    

  FreeArray(Indices())
	
EndProcedure

; Create the Model an releases the primitive object
Procedure Model_SetModel(*this.Model_Template)
  *this\VertexArray = *this\Primitive\GetVerticesArray()  
  *this\IntexArray  = *this\Primitive\GetIndexArray()
  *this\Mesh\SetStride(*this\Primitive\VertexSize())
  *this\Primitive\Release()
  *this\Primitive = #Null  
  *this\Mesh\CreateBuffer(*this\VertexArray, *this\IntexArray)  
EndProcedure



; Render the model
Procedure Model_Render(*this.Model_Template)  
  *this\Mesh\Render()    
EndProcedure

Procedure Model_Release(*this.Model_Template) 
  *this\Mesh\Release()
  If *this\Primitive    : *this\Primitive\Release()     : EndIf  
  If *this\VertexArray  : FreeMemory(*this\VertexArray) : EndIf
  If *this\IntexArray   : FreeMemory(*this\IntexArray)  : EndIf  
  If *this\Texture      : *this\Texture\Release()       : EndIf
  FreeMemory(*this)
EndProcedure






;-//    Private procedures    //

;/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
;/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
;/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
;/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
;/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
;-//    DataSection    //
DataSection
  Model_Class:   
  Data.i @Model_GetPrimitive()
  Data.i @Model_GetMesh()
  Data.i @Model_LoadTexture()
  Data.i @Model_AddTriangle()
  Data.i @Model_AddRectangle()
  Data.i @Model_AddCube()
  Data.i @Model_SetModel()
  Data.i @Model_Render()
  Data.i @Model_Release()
EndDataSection 

; IDE Options = PureBasic 5.20 beta 14 LTS (Windows - x64)
; CursorPosition = 84
; FirstLine = 77
; Folding = --
; EnableXP
; EnableCompileCount = 0
; EnableBuildCount = 0